//package cn.sw.cloudmybatisplus.common.mapper;
//
//import java.lang.reflect.Field;
//
//public class Mapper {
//
//    public static <S, T> T map(S source, Class<T> targetClass) throws Exception {
//        T target = targetClass.getDeclaredConstructor().newInstance();
//        mapFields(source, target);
//        return target;
//    }
//
//    private static void mapFields(Object source, Object target) throws IllegalAccessException {
//        if (source == null || target == null) {
//            return;
//        }
//
//        Class<?> sourceClass = source.getClass();
//        Class<?> targetClass = target.getClass();
//
//        // Map fields from source to target, including fields in superclasses
//        mapFieldsRecursive(source, target, sourceClass, targetClass);
//    }
//
//    private static void mapFieldsRecursive(Object source, Object target, Class<?> sourceClass, Class<?> targetClass) throws IllegalAccessException {
//        if (sourceClass == null || targetClass == null || sourceClass.equals(Object.class)) {
//            return;
//        }
//
//        // Map fields from source to target
//        for (Field sourceField : sourceClass.getDeclaredFields()) {
//            sourceField.setAccessible(true);
//            Field targetField = getFieldByName(targetClass, sourceField.getName());
//            if (targetField != null) {
//                targetField.setAccessible(true);
//                if (sourceField.getType().equals(targetField.getType())) {
//                    targetField.set(target, sourceField.get(source));
//                }
//            }
//        }
//
//        // Recursively map fields from superclasses
//        mapFieldsRecursive(source, target, sourceClass.getSuperclass(), targetClass.getSuperclass());
//    }
//
//    private static Field getFieldByName(Class<?> clazz, String fieldName) {
//        if (clazz == null) {
//            return null;
//        }
//        try {
//            return clazz.getDeclaredField(fieldName);
//        } catch (NoSuchFieldException e) {
//            // Recursively search in the superclass
//            return getFieldByName(clazz.getSuperclass(), fieldName);
//        }
//    }
//}
package cn.sw.cloudmybatisplus.common.mapper;

import java.lang.reflect.Field;
import java.util.logging.Logger;

public class Mapper {
    private static final Logger logger = Logger.getLogger(Mapper.class.getName());

    public static <S, T> T map(S source, Class<T> targetClass) throws Exception {
        logger.info("Mapping from " + source.getClass().getName() + " to " + targetClass.getName());
        T target = targetClass.getDeclaredConstructor().newInstance();
        mapFields(source, target);
        return target;
    }

    private static void mapFields(Object source, Object target) throws IllegalAccessException {
        if (source == null || target == null) {
            logger.warning("Source or target is null");
            return;
        }

        Class<?> sourceClass = source.getClass();
        Class<?> targetClass = target.getClass();

        logger.info("Source class: " + sourceClass.getName());
        logger.info("Target class: " + targetClass.getName());

        // Map fields from source to target, including fields in superclasses
        mapFieldsRecursive(source, target, sourceClass, targetClass);
    }

    private static void mapFieldsRecursive(Object source, Object target, Class<?> sourceClass, Class<?> targetClass) throws IllegalAccessException {
        if (sourceClass == null || targetClass == null || sourceClass.equals(Object.class)) {
            logger.info("End of recursion");
            return;
        }

        logger.info("Mapping fields from " + sourceClass.getName() + " to " + targetClass.getName());

        // Map fields from source to target
        for (Field sourceField : sourceClass.getDeclaredFields()) {
            sourceField.setAccessible(true);
            Field targetField = getFieldByName(targetClass, sourceField.getName());
            if (targetField != null) {
                targetField.setAccessible(true);
                if (sourceField.getType().equals(targetField.getType())) {
                    targetField.set(target, sourceField.get(source));
                    logger.info("Mapped field: " + sourceField.getName() + " from " + sourceClass.getName() + " to " + targetClass.getName());
                } else {
                    logger.warning("Field type mismatch: " + sourceField.getName() + " in " + sourceClass.getName() + " and " + targetClass.getName());
                }
            } else {
                logger.warning("Field not found in target: " + sourceField.getName() + " in " + targetClass.getName());
            }
        }

        // Recursively map fields from superclasses
        mapFieldsRecursive(source, target, sourceClass.getSuperclass(), targetClass.getSuperclass());
    }

    private static Field getFieldByName(Class<?> clazz, String fieldName) {
        if (clazz == null) {
            logger.info("Class is null, end of search");
            return null;
        }
        try {
            logger.info("Searching for field: " + fieldName + " in " + clazz.getName());
            return clazz.getDeclaredField(fieldName);
        } catch (NoSuchFieldException e) {
            logger.info("Field not found in " + clazz.getName() + ", searching in superclass");
            // Recursively search in the superclass
            return getFieldByName(clazz.getSuperclass(), fieldName);
        }
    }
}
